/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bef.core.action.modify;


import com.inspur.edp.bef.api.action.VoidActionResult;
import com.inspur.edp.bef.api.action.assembler.IMgrActionAssembler;
import com.inspur.edp.bef.api.be.BefLockType;
import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.api.be.IBusinessEntity;
import com.inspur.edp.bef.api.exceptions.ErrorCodes;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.api.parameter.retrieve.RetrieveResult;
import com.inspur.edp.bef.core.action.AuthorityUtil;
import com.inspur.edp.bef.core.action.base.ActionUtil;
import com.inspur.edp.bef.core.lock.LockUtils;
import com.inspur.edp.bef.core.session.FuncSessionManager;
import com.inspur.edp.bef.entity.exception.BefExceptionBase;
import com.inspur.edp.bef.entity.exception.ExceptionLevel;
import com.inspur.edp.bef.spi.action.AbstractManagerAction;
import com.inspur.edp.bef.spi.entity.builtinimpls.BefModelResInfoImpl;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MultiModifyMgrAction extends AbstractManagerAction<VoidActionResult>
{

		//region Constructor

	public MultiModifyMgrAction(IBEManagerContext managerContext, java.util.ArrayList<IChangeDetail> changeList)
	{
		super(managerContext);
		ActionUtil.requireNonNull(changeList, "changeList");
		this.changeList = changeList;
	}

		//endregion


		//region 属性字段

	private java.util.ArrayList<IChangeDetail> changeList;


		//endregion


		//region  Override

	@Override
	public final void execute()
	{
		getBEManagerContext().checkAuthority("Modify");
//		AuthorityUtil.checkAuthority("Modify");
//		FuncSessionManager.getCurrentSession().getBefContext().setCurrentOperationType("Modify");
		List<String> ids = changeList.stream().map(item -> item.getDataID()).collect(Collectors.toList());
		RetrieveParam tempVar = new RetrieveParam();
		tempVar.setNeedLock(true);
		RetrieveParam para = tempVar;
		RetrieveResult result = getBEManagerContext().getBEManager().retrieve(ids, para);

		checkRetrieveResult(ids, result);

		Map<String, IBusinessEntity> beList = getBEManagerContext().getEntitiesMap(ids);
		for(IChangeDetail change : changeList){
			beList.get(change.getDataID()).modify(change);
		}
	}

	/** 
	 检验Retrieve结果，若未全部获取成功，则抛异常，并返回失败ids
	 
	 @param ids 批量Modify的数据id
	 @param result 获取结果
	*/
	private void checkRetrieveResult(List<String> ids, RetrieveResult result)
	{
		List<Object> resultIds = result.getDatas().keySet().stream().collect(Collectors.toList());
		if (resultIds.size() != ids.size()) {
			java.util.ArrayList<String> retrieveFailIDs = new java.util.ArrayList<String>();
			for (String id : ids) {
				if (!resultIds.contains(id)) {
					retrieveFailIDs.add(id);
				}
			}
			throw new BefExceptionBase(ErrorCodes.ModifyingNonExistence,
					String.format("批量修改时，ID为以下值的数据不存在：%1$s，请确认ID是否正确或数据是否已被删除", retrieveFailIDs), null,
					ExceptionLevel.Error, true);
		}
		if(!LockUtils.needLock(getBEManagerContext().getModelResInfo()))
			return;
		if (!result.getLockFailedIds().isEmpty())
		{
			LockUtils.throwLockFailed(result.getLockFailedIds().stream().collect(Collectors.toList()), null);
			//throw new BefException(ErrorCodes.EditingLocked, "数据已被其他用户锁定无法修改");//TODO: 使用统一的消息机制
		}
	}

	@Override
	protected final IMgrActionAssembler getMgrAssembler()
	{
		return getMgrActionAssemblerFactory().getMultiModifyMgrActionAssembler(getBEManagerContext(), changeList);
	}

		//endregion
}
